package cn.org.xwb.bookmall.user.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.org.xwb.bookmall.model.constant.AccountConst;
import cn.org.xwb.bookmall.model.po.Orders;
import cn.org.xwb.bookmall.model.po.Product;
import cn.org.xwb.bookmall.model.po.ProductOptions;
import cn.org.xwb.bookmall.model.service.impl.CommentsServiceImpl;
import cn.org.xwb.bookmall.model.service.impl.OrdersServiceImpl;
import cn.org.xwb.bookmall.model.service.impl.ProductOptionsServiceImpl;
import cn.org.xwb.bookmall.model.service.impl.ProductServiceImpl;
import cn.org.xwb.bookmall.model.vo.AddCommentVo;
import cn.org.xwb.bookmall.model.vo.OrderVo;
import cn.org.xwb.bookmall.model.vo.ProductVo;
import cn.org.xwb.bookmall.user.annotation.IsLoginParam;
import cn.org.xwb.common.encrypt.annotation.des.DesEn;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDe;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDeObj;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDeParam;
import cn.org.xwb.common.encrypt.constant.EncryptConstant;
import cn.org.xwb.common.error.annotation.ServerErrorCatch;
import cn.org.xwb.common.model.vo.RespResult;
import cn.org.xwb.common.valid.annotation.nu.NotNull;
import cn.org.xwb.common.valid.annotation.nu.NotNullObj;
import cn.org.xwb.common.valid.annotation.nu.NotNullParam;
import cn.org.xwb.common.valid.annotation.str.StrNotNull;
import cn.org.xwb.common.valid.annotation.str.StrNotNullObj;
import cn.org.xwb.common.valid.annotation.str.StrNotNullParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/order")
public class UserOrderController {

    @Autowired
    private OrdersServiceImpl ordersService;

    @Autowired
    private UserCarController userCarController;

    @Autowired
    private ProductServiceImpl productService;

    @Autowired
    private ProductOptionsServiceImpl productOptionsService;

    @PostMapping("/add")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @Transactional
    public RespResult<Object> addOrder(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @StrNotNullObj @NotNullObj @RsaDeObj
            OrderVo orderVo
    ) {
        // 需要删除购物车，删除购物车
        if (Objects.nonNull(orderVo.getCarId())) {
            RespResult<Object> respResult = userCarController.delCarProduct(orderVo.getUserId(), orderVo.getCarId());
            if (!respResult.getStatus()) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RespResult.fail("订单提交失败");
            }
        }
        orderVo.setCreateTime(new Date());
        orderVo.setUpdateTime(new Date());
        Orders orders = Convert.convert(Orders.class, orderVo);
        int res = ordersService.getBaseMapper().insert(orders);
        if (res < 1) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单提交失败");
        }
        List<OrderVo> orderVos = ordersService.findAndCacheAll();
        if (Objects.isNull(orderVos)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单提交失败");
        }
        return RespResult.success("订单提交成功", orders.getId());
    }

    @PostMapping("/pay")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @Transactional
    public RespResult<Object> payOrder(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @NotNullParam
            Long orderId,
            @NotNullParam
            Integer status
    ) {
        Orders orders = ordersService.getById(orderId);
        Product product = productService.getById(orders.getProductId());
        product.setSale(product.getSale() + orders.getNum());
        boolean res = productService.updateById(product);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单支付失败");
        }
        ProductOptions productOptions = productOptionsService.getById(orders.getProductOptionId());
        productOptions.setStock(productOptions.getStock() - orders.getNum());
        res = productOptionsService.updateById(productOptions);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单支付失败");
        }
        List<ProductVo> productVoList = productService.getAllAndCache();
        if (Objects.isNull(productVoList)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单支付失败");
        }
        orders.setStatus(status);
        orders.setUpdateTime(new Date());
        res = ordersService.updateById(orders);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单支付失败");
        }
        List<OrderVo> orderVoList = ordersService.findAndCacheAll();
        if (Objects.isNull(orderVoList)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单支付失败");
        }
        return RespResult.success("订单支付成功");
    }

    @GetMapping("/all")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @DesEn
    public RespResult<Object> allOrder(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey,
            @NotNullParam
            Long userId
    ) {
        List<OrderVo> orderVoList = ordersService.findFromCache();
        Collections.reverse(orderVoList);
        orderVoList = orderVoList.stream().filter(orderVo -> orderVo.getUserId() == userId).toList();
        return RespResult.success("获取订单列表成功", orderVoList);
    }

    @PostMapping("/update")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @Transactional
    public RespResult<Object> updateOrder(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @NotNullParam
            Long orderId,
            @NotNullParam
            Integer status
    ) {
        Orders orders = new Orders();
        orders.setId(orderId);
        orders.setStatus(status);
        orders.setUpdateTime(new Date());
        boolean res = ordersService.updateById(orders);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单信息更新失败");
        }
        List<OrderVo> orderVoList = ordersService.findAndCacheAll();
        if (Objects.isNull(orderVoList)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("订单信息更新失败");
        }
        return RespResult.success("订单信息更新成功");
    }

    @PostMapping("/cancel")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    @Transactional
    public RespResult<Object> cancelOrder(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @NotNullParam
            Long orderId,
            @NotNullParam
            Integer status
    ) {
        Orders orders = ordersService.getById(orderId);
        Product product = productService.getById(orders.getProductId());
        product.setSale(product.getSale() - orders.getNum());
        boolean res = productService.updateById(product);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("取消订单失败");
        }
        ProductOptions productOptions = productOptionsService.getById(orders.getProductOptionId());
        productOptions.setStock(productOptions.getStock() + orders.getNum());
        res = productOptionsService.updateById(productOptions);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("取消订单失败");
        }
        List<ProductVo> productVoList = productService.getAllAndCache();
        if (Objects.isNull(productVoList)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("取消订单失败");
        }
        orders.setStatus(status);
        orders.setUpdateTime(new Date());
        res = ordersService.updateById(orders);
        if (!res) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("取消订单失败");
        }
        List<OrderVo> orderVoList = ordersService.findAndCacheAll();
        if (Objects.isNull(orderVoList)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RespResult.fail("取消订单失败");
        }
        return RespResult.success("取消订单成功");
    }

    @Autowired
    private CommentsServiceImpl commentsService;

    @PostMapping("/comment")
    @ServerErrorCatch
    @StrNotNull
    @NotNull
    @RsaDe
    @IsLoginParam
    public RespResult<Object> addComment(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @NotNullObj @StrNotNullObj @RsaDeObj
            AddCommentVo addCommentVo
            // @NotNullParam
            // Long orderId,
            // @NotNullParam
            // Long productId,
            // @NotNullParam
            // Long userId,
            // @StrNotNullParam @RsaDeParam
            // String content,
            // @NotNullParam
            // Integer score,
            // @RequestParam(value = "img", required = false)
            // List<String> img
    ) {
        Boolean res = commentsService.addComment(
                addCommentVo.getOrderId(),
                addCommentVo.getProductId(),
                addCommentVo.getUserId(),
                addCommentVo.getContent(),
                addCommentVo.getScore(),
                addCommentVo.getImg()
        );
        if (!res) {
            return RespResult.fail("商品评价失败");
        }
        return RespResult.success("商品评价成功");
    }

}
